#ifndef THREADPOOL_H
#define THREADPOOL_H
#include <pthread.h>
#include <list>
#include <exception>
#include <cstdio>
#include "locker.h"

// 线程池类 定义成模板类，为了代码的复用 模板参数T为任务类
template<typename T>
class threadpool {
   private:
    int m_thread_number;

    // 线程池数组， 大小为m_thread_number
    pthread_t* m_threads;

    // 请求队列中最多允许的等待处理的请求数量
    int m_max_requests;

    // 请求队列
    std::list< T*> m_workqueue;

    // 互斥锁
    locker m_queueLocker;

    // 信号量用来判断是否有任务
    sem m_queueStat;

    // 是否结束线程
    bool m_stop;

private:
    static void* worker(void* arg);
    void run();

   public:
    threadpool(int threadNumber=8, int maxRequests=10000);
    ~threadpool();

    bool append(T* request);

};

template<typename T>
threadpool<T>::threadpool(int threadNumber, int maxRequests):
    m_thread_number(threadNumber),
    m_max_requests(maxRequests),
    m_stop(false),
    m_threads(NULL){

        if (threadNumber <= 0 || maxRequests <= 0){
            throw std::exception();
        }

        m_threads = new pthread_t[m_thread_number];
        if (!m_threads){
            throw std::exception();
        }

        // 创建threadNumber个线程并将其设置为线程脱离
        for (int i=0;i<m_thread_number;++i){
            printf("create the %d thread \n", i);
            if (pthread_create(m_threads+i, NULL, worker, this) != 0){
                delete[] m_threads;
                throw std::exception();
            }

            if (pthread_detach(m_threads[i])){
                delete[] m_threads;
                throw std::exception();
            }
        }
    }

template<typename T>
threadpool<T>::~threadpool(){
    delete[] m_threads;
    m_stop = true;
}

template<typename T>
bool threadpool<T>::append(T* request){
    m_queueLocker.lock();
    if (m_workqueue.size() > m_max_requests){
        // 已经超出最大值
        m_queueLocker.unlock();
        return false;
    }

    m_workqueue.push_back(request);

    m_queueLocker.unlock();

    m_queueStat.post();
    return true;
}

template<typename T>
void* threadpool<T>::worker(void* arg){
    threadpool* pool = (threadpool*)arg;
    pool->run();

    return pool;
}

template<typename T>
void threadpool<T>::run(){
    while(!m_stop){
        m_queueStat.wait(); // 如果说信号量有值则不阻塞 通过此种方式判断有没有任务可以做
        m_queueLocker.lock(); // 上锁操作队列
        if (m_workqueue.empty()){
            // 队列为空 直接解锁 下一次循环
            m_queueLocker.unlock();
            continue;
        }

        T* request = m_workqueue.front();
        m_workqueue.pop_front();
        m_queueLocker.unlock();

        if (!request){
            continue;
        }
        // TODO 任务类
        request->process(); 
    }

}

#endif